﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.IO;

namespace Common
{
	public sealed class DuplicateStringFinder
	{
		private string m_resourceFile = string.Empty;
		List<KeyValuePair<string, string>> m_strings = null;
		Common.Entities.DetailedProjectInfo m_projInfo = null;
		private string m_projRootFolder = null;

		System.Collections.Concurrent.BlockingCollection<Common.Entities.DuplicateStringInfo> m_blockColl = null;

		public DuplicateStringFinder(string pathToResxFile, Common.Entities.DetailedProjectInfo info)
		{
			if (string.IsNullOrEmpty(pathToResxFile))
				throw new ArgumentException("pathToResxFile");

			if (info == null)
				throw new ArgumentNullException("info");

			m_resourceFile = pathToResxFile;
			m_strings = new List<KeyValuePair<string, string>>();
			m_projInfo = info;
			m_blockColl = new System.Collections.Concurrent.BlockingCollection<Common.Entities.DuplicateStringInfo>();
			m_projRootFolder = m_projInfo.ProjectRootPath;
		}

		private void LoadStrings()
		{
			XDocument doc = XDocument.Load(m_resourceFile);
			m_strings.Clear();

			foreach (XElement element in doc.Root.Elements("data"))
			{
				m_strings.Add(new KeyValuePair<string, string>(element.Attribute("name").Value, element.Element("value").Value));
			}
			doc = null;
		}

		public IEnumerable<Common.Entities.DuplicateStringInfo> Process()
		{
			LoadStrings();

			foreach (KeyValuePair<string, string> pair in m_strings)
			{
				Common.Entities.DuplicateStringInfo duplInfo = new Common.Entities.DuplicateStringInfo();
				duplInfo.ResourceName = pair.Key;
				duplInfo.ResourceString = pair.Value;

				System.Threading.Tasks.Parallel.ForEach<Common.Entities.ProjectFileInfo>(m_projInfo.CompiledFiles, file =>
				{
					string fullPath = System.IO.Path.Combine(m_projRootFolder, file.File);
					if (!System.IO.File.Exists(fullPath) || string.Compare(System.IO.Path.GetExtension(fullPath), ".cs") != 0)
					{
						return;
					}

					System.Diagnostics.Debug.WriteLine(pair.Value);
					System.Diagnostics.Debug.WriteLine(fullPath);

					using (StreamReader sr = new StreamReader(fullPath))
					{
						string text = sr.ReadToEnd();
						sr.Close();

						int count = 0;
						int index = -1;
						int offset = 0;
						while ((index = text.IndexOf(pair.Value, offset)) != -1)
						{
							count++;
							offset = index + pair.Value.Length;
						}

						if (count > 0)
							duplInfo.OccurrencesInFile.Add(fullPath, count);

						text = null;
					}
				});

				m_blockColl.Add(duplInfo);
			}
			m_blockColl.CompleteAdding();

			return m_blockColl.GetConsumingEnumerable();
		}

	}
}
